package com.ruoyi.system.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.PropertyChange;
import com.ruoyi.system.domain.PropertyPicture;
import com.ruoyi.system.enums.ExcelFieldEnum;
import com.ruoyi.system.kiteUtils.CommUtils;
import com.ruoyi.system.mapper.PropertyChangeMapper;
import com.ruoyi.system.mapper.PropertyPictureMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.PropertyShebeiMapper;
import com.ruoyi.system.domain.PropertyShebei;
import com.ruoyi.system.service.IPropertyShebeiService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * 实验设备Service业务层处理
 *
 * @author kite
 * @date 2025-03-24
 */
@Service
public class PropertyShebeiServiceImpl implements IPropertyShebeiService {
    @Autowired
    private PropertyShebeiMapper propertyShebeiMapper;

    @Autowired
    private PropertyChangeMapper propertyChangeMapper;

    @Autowired
    private PropertyPictureMapper propertyPictureMapper;

    /**
     * 查询实验设备
     *
     * @param id 实验设备主键
     * @return 实验设备
     */
    @Override
    public PropertyShebei selectPropertyShebeiById(Long id) {
        return propertyShebeiMapper.selectPropertyShebeiById(id);
    }

    /**
     * 查询实验设备列表
     *
     * @param propertyShebei 实验设备
     * @return 实验设备
     */
    @Override
    public List<PropertyShebei> selectPropertyShebeiList(PropertyShebei propertyShebei) {
        List<PropertyShebei> list = propertyShebeiMapper.selectPropertyShebeiList(propertyShebei);
        for (PropertyShebei item : list) {
            PropertyPicture propertyPicture = propertyPictureMapper.selectByNameAndType(item.getInstrumentName(), "1");
            if (propertyPicture != null) {
                item.setPictureUrl(propertyPicture.getPictureUrl());
            }
            item.setChangeSize(propertyChangeMapper.selectCountByNumberAndType(item.getInstrumentNumber(), "设备资产"));
        }
        return list;
    }

    /**
     * 新增实验设备
     *
     * @param propertyShebei 实验设备
     * @return 结果
     */
    @Override
    @Transactional // 添加事务注解确保两个操作原子性
    public int insertPropertyShebei(PropertyShebei propertyShebei) {
        // 校验设备编号
        PropertyShebei existing = propertyShebeiMapper.selectPropertyShebeiByNumber(propertyShebei.getInstrumentNumber());
        if (existing != null) {
            throw new ServiceException("设备编号 " + propertyShebei.getInstrumentNumber() + " 已存在");
        }
        //校验数据
        checkPropertyShebei(propertyShebei);
        // 2. 插入设备数据
        //设备数据中的修订人永远是该系统登入人

        int rows = propertyShebeiMapper.insertPropertyShebei(propertyShebei);
        if (rows <= 0) {
            return rows;
        }
        // 3. 记录变更日志
        addPropertyChange4Insert(propertyShebei, "新增");
        return rows;
    }


    /**
     * 修改实验设备
     *
     * @param propertyShebei 实验设备
     * @return 结果
     */
    @Override
    @Transactional
    public int updatePropertyShebei(PropertyShebei propertyShebei) {
        checkPropertyShebei(propertyShebei);
        // 1. 查询原始数据
        PropertyShebei originalShebei = propertyShebeiMapper.selectPropertyShebeiById(propertyShebei.getId());
        // 2. 执行更新操作
        int result = propertyShebeiMapper.updatePropertyShebei(propertyShebei);
        // 3.添加变更流水
        addPropertyChange4Update(originalShebei, propertyShebei, "设备资产修改");
        return result;
    }

    /**
     * 批量删除实验设备
     *
     * @param ids 需要删除的实验设备主键
     * @return 结果
     */
    @Override
    public int deletePropertyShebeiByIds(Long[] ids) {
        return propertyShebeiMapper.deletePropertyShebeiByIds(ids);
    }

    /**
     * 删除实验设备信息
     *
     * @param id 实验设备主键
     * @return 结果
     */
    @Override
    public int deletePropertyShebeiById(Long id) {
        return propertyShebeiMapper.deletePropertyShebeiById(id);
    }

    @Override
    @Transactional
    public void importData(MultipartFile file) {
        List<PropertyShebei> list;
        ExcelUtil<PropertyShebei> excelUtil = new ExcelUtil<>(PropertyShebei.class);
        try {
            list = excelUtil.importExcel(file.getInputStream());
        } catch (Exception e) {
            throw new ServiceException("文件读取失败,请检查文件格式是否正确！");
        }
        StringBuilder errMsg = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            PropertyShebei item = list.get(i);
            try {
                PropertyShebei existing = propertyShebeiMapper.selectPropertyShebeiByNumber(item.getInstrumentNumber());
                if (existing != null) {
                    throw new ServiceException("该设备的仪器编号 " + item.getInstrumentNumber() + " 已存在");
                }
                checkPropertyShebei(item);

                SysUser user = getLoginSysUser();
                item.setRevisedPeople(user.getUserName());//工号
                item.setBackupFields9(user.getNickName());//姓名

                propertyShebeiMapper.insertPropertyShebei(item);
                addPropertyChange4Insert(item, "批量新增");
            } catch (ServiceException e) {
                errMsg.append("第").append(i + 2).append("行错误，").append(e.getMessage()).append("</br>");
            }
        }
        if (StringUtils.isNotBlank(errMsg)) {
            throw new ServiceException(errMsg.toString());
        }
    }

    @Override
    @Transactional
    public void batchEdit(MultipartFile file) {
        List<PropertyShebei> list;
        ExcelUtil<PropertyShebei> excelUtil = new ExcelUtil<>(PropertyShebei.class);
        try {
            list = excelUtil.importExcel(file.getInputStream());
        } catch (Exception e) {
            throw new ServiceException("文件读取失败,请检查文件格式是否正确！");
        }
        StringBuilder errMsg = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            PropertyShebei item = list.get(i);
            try {
                checkPropertyShebei(item);
                // 1. 查询原始数据
                PropertyShebei originalShebei = propertyShebeiMapper.selectPropertyShebeiByNumber(item.getInstrumentNumber());
                if (originalShebei == null) {
                    throw new ServiceException("根据仪器编号，系统未找到该设备资产");
                }
                item.setId(originalShebei.getId());
                // 2. 执行更新操作
                //永远插入登入人的工号姓名作为变更人信息
                SysUser user = getLoginSysUser();
                item.setRevisedPeople(user.getUserName());//工号
                item.setBackupFields9(user.getNickName());//姓名

                propertyShebeiMapper.updatePropertyShebei(item);
                // 3.添加变更流水
                addPropertyChange4Update(originalShebei, item, "批量修改");
            } catch (ServiceException e) {
                errMsg.append("第").append(i + 2).append("行错误，").append(e.getMessage()).append("</br>");
            }
        }
        if (StringUtils.isNotBlank(errMsg)) {
            throw new ServiceException(errMsg.toString());
        }
    }


    //校验设备
    private void checkPropertyShebei(PropertyShebei propertyShebei) {
        if (StringUtils.isBlank(propertyShebei.getInstrumentNumber())) {
            throw new ServiceException("【仪器编号】不能为空");
        }
        if (StringUtils.isBlank(propertyShebei.getInstrumentName())) {
            throw new ServiceException("【仪器名称】不能为空");
        }
        if (StringUtils.isBlank(propertyShebei.getStorageLocation())) {
            throw new ServiceException("【存放地】不能为空");
        }
        if (StringUtils.isBlank(propertyShebei.getRevisedReason())) {
            throw new ServiceException("【最新修订事由】不能为空");
        }
//        try {
//            CommUtils.findUserCode(propertyShebei.getRevisedPeople());
//        } catch (ServiceException e) {
//            throw new ServiceException("【最新修订人】的user_code未找到，请重新检查或联系管理员");
//        }
        try {
            CommUtils.findUserCode(propertyShebei.getUser());
        } catch (ServiceException e) {
            throw new ServiceException("【使用人】的user_code未找到，请重新检查或联系管理员");
        }
        try {
            CommUtils.findUserCode(propertyShebei.getKeeper());
        } catch (ServiceException e) {
            throw new ServiceException("【保管人】的user_code未找到，请重新检查或联系管理员");
        }
        try {
            CommUtils.findUserCode(propertyShebei.getResponser());
        } catch (ServiceException e) {
            throw new ServiceException("【责任人】的user_code未找到，请重新检查或联系管理员");
        }
    }

    private void addPropertyChange4Insert(PropertyShebei propertyShebei, String type) {
        PropertyChange changeLog = new PropertyChange();
        changeLog.setInstrumentNumber(propertyShebei.getInstrumentNumber()); //编号
        changeLog.setBackupFields1(propertyShebei.getInstrumentName());//名称
        // 变更情况改为动态生成
        StringBuilder changeDetail = new StringBuilder("【新增设备资产】");
        List<Map<ExcelFieldEnum, String>> excelFields = CommUtils.getExcelFields(propertyShebei);
        for (Map<ExcelFieldEnum, String> map : excelFields) {
            String value = map.get(ExcelFieldEnum.FILED_VALUE);
            String excelAnnotationName = map.get(ExcelFieldEnum.EXCEL_ANNOTATION_NAME);
            if (StringUtils.isNotBlank(value)) {
                changeDetail.append(excelAnnotationName).append("：").append(value).append("；");
            }
        }
        changeLog.setChangeSituationStatus(changeDetail.toString()); //变更情况
        // 操作人信息
        String revisedPeople = propertyShebei.getRevisedPeople();
        revisedPeople = StringUtils.isNotBlank(revisedPeople) ? revisedPeople : SecurityUtils.getUsername();
        changeLog.setChangeSituationPerson(revisedPeople);//变更人
        // 时间信息
        String revisedTm = propertyShebei.getRevisedTm();
        revisedTm = StringUtils.isNotBlank(revisedTm) ? revisedTm : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        changeLog.setChangeSituationTm(revisedTm); //变更时间
        // 变更事由
        String revisedReason = propertyShebei.getRevisedReason();
        changeLog.setChangeSituationResason(StringUtils.isNotBlank(revisedReason) ? revisedReason : "初始入库"); //变更事由
        // 操作类型标记
        changeLog.setBackupFields2(type); //变更类型
        changeLog.setBackupFields3("设备资产");
        changeLog.setBackupFields4(propertyShebei.getStorageLocation());//存放地
        changeLog.setBackupFields5(propertyShebei.getKeeper());//保管人
        changeLog.setBackupFields6(propertyShebei.getUser());//使用人
        changeLog.setBackupFields7(propertyShebei.getResponser());//责任人
        changeLog.setBackupFields8(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        changeLog.setBackupFields9(propertyShebei.getBackupFields9());
        propertyChangeMapper.insertPropertyChange(changeLog);
    }

    private void addPropertyChange4Update(PropertyShebei originalShebei, PropertyShebei newShebei, String updateType) {
        PropertyChange changeLog = new PropertyChange();
        changeLog.setInstrumentNumber(newShebei.getInstrumentNumber()); //编号
        changeLog.setBackupFields1(newShebei.getInstrumentName());//名称
        StringBuilder changeDetail = new StringBuilder("【修改设备资产】，");
        List<Map<ExcelFieldEnum, String>> oldExcelFields = CommUtils.getExcelFields(originalShebei);
        List<Map<ExcelFieldEnum, String>> newExcelFields = CommUtils.getExcelFields(newShebei);
        int changeSize = 0;
        for (int i = 0; i < oldExcelFields.size(); i++) {
            String oldFileValue = oldExcelFields.get(i).get(ExcelFieldEnum.FILED_VALUE);
            String newFileValue = newExcelFields.get(i).get(ExcelFieldEnum.FILED_VALUE);
            if (StringUtils.isNotBlank(oldFileValue) || StringUtils.isNotBlank(newFileValue)) {
                if (!StringUtils.equals(oldFileValue, newFileValue)) {
                    changeDetail.append(oldExcelFields.get(i).get(ExcelFieldEnum.EXCEL_ANNOTATION_NAME))
                            .append("从“").append(oldFileValue).append("”修改为“").append(newFileValue).append("”；");
                    changeSize++;
                }
            }
        }
        if (changeSize == 0) {
            throw new ServiceException("数据未修改，无法变更");
        }
        changeLog.setChangeSituationStatus(changeDetail.toString()); //变更情况

        // 操作人信息
        String revisedPeople = newShebei.getRevisedPeople();
        revisedPeople = StringUtils.isNotBlank(revisedPeople) ? revisedPeople : SecurityUtils.getUsername();
        changeLog.setChangeSituationPerson(revisedPeople);//变更人

        // 时间信息
        String revisedTm = newShebei.getRevisedTm();
        revisedTm = StringUtils.isNotBlank(revisedTm) ? revisedTm : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        changeLog.setChangeSituationTm(revisedTm); //变更时间

        // 变更事由
        String revisedReason = newShebei.getRevisedReason();
        changeLog.setChangeSituationResason(StringUtils.isNotBlank(revisedReason) ? revisedReason : ""); //变更事由

        // 操作类型标记
        changeLog.setBackupFields2(updateType); //变更类型
        changeLog.setBackupFields3("设备资产");

        changeLog.setBackupFields4(newShebei.getStorageLocation());//存放地
        changeLog.setBackupFields5(newShebei.getKeeper());//保管人
        changeLog.setBackupFields6(newShebei.getUser());//使用人
        changeLog.setBackupFields7(newShebei.getResponser());//责任人
        changeLog.setBackupFields8(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        changeLog.setBackupFields9(newShebei.getBackupFields9());
        propertyChangeMapper.insertPropertyChange(changeLog);
    }
    private SysUser getLoginSysUser() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            throw new RuntimeException("请先登录");
        }
        SysUser user = loginUser.getUser();
        if (user == null) {
            throw new RuntimeException("当前用户信息为空");
        }
        return user;
    }
}
